#version 150

layout(std140) uniform Fog {
    vec4  FogColor;
    float FogEnvironmentalStart;
    float FogEnvironmentalEnd;
    float FogRenderDistanceStart;
    float FogRenderDistanceEnd;
    float FogSkyEnd;
    float FogCloudsEnd;
};

float linear_fog_value(float vertexDistance, float fogStart, float fogEnd) {
    if (vertexDistance <= fogStart) {
        return 0.0;
    } else if (vertexDistance >= fogEnd) {
        return 1.0;
    }

    return (vertexDistance - fogStart) / (fogEnd - fogStart);
}

float total_fog_value(float sphericalVertexDistance, float cylindricalVertexDistance, float environmentalStart, float environmantalEnd, float renderDistanceStart, float renderDistanceEnd) {
    float start_multiplier = 0.85;
    float end_multiplier = 1.0;

    float modifiedRenderDistanceStart = renderDistanceStart * start_multiplier;
    float modifiedRenderDistanceEnd   = renderDistanceEnd   * end_multiplier;

    float environmentalFog = linear_fog_value(sphericalVertexDistance, environmentalStart, environmantalEnd);
    float playerCentricFog = linear_fog_value(cylindricalVertexDistance, modifiedRenderDistanceStart, modifiedRenderDistanceEnd);

    return max(environmentalFog, playerCentricFog);
}

vec4 apply_fog(vec4 inColor, float sphericalVertexDistance, float cylindricalVertexDistance, float environmentalStart, float environmantalEnd, float renderDistanceStart, float renderDistanceEnd, vec4 fogColor) {
    float fogValue = total_fog_value(sphericalVertexDistance, cylindricalVertexDistance, environmentalStart, environmantalEnd, renderDistanceStart, renderDistanceEnd);
    return vec4(mix(inColor.rgb, fogColor.rgb, fogValue * fogColor.a), inColor.a);
}

float fog_spherical_distance(vec3 pos) {
    return length(pos);
}

float fog_cylindrical_distance(vec3 pos) {
    float distXZ = length(pos.xz);
    float distY  = abs(pos.y);
    return max(distXZ, distY);
}
